const mongodb = require('../config/config.default')({}).mongoose

const mongoose = require('mongoose')

const app = {}

mongoose.connect(mongodb.url)
app.mongoose = mongoose

const Stream = require('../app/model/stream')(app)
const Server = require('../app/model/server')(app)
const Action = require('../app/model/action')(app)
const Error = require('../app/model/error')(app)
const Rule = require('../app/model/rule')(app)

async function action(id, host, key, value, user) {
  console.log('记录告警', id)
  const target = await Action.findById(id)
  if (!target) return
  switch (target.type) {
    // 站内告警
    case 4:
      await Error.create({
        title: target.name,
        action: id,
        point: { [key]: value },
        server: host,
        user,
      })
      break
    default:
      await Error.create({
        title: target.name,
        action: id,
        point: { [key]: value },
        server: host,
        user,
      })
      break
  }
}

async function rules(server, _data) {
  let rules = await Rule.find({})
  console.log(rules.length)
  // 包含有信息
  rules = rules.filter($ => $.server.join(',').includes(server._id.toString()))[0]

  if (rules) {
    const { data } = _data
    const rule = rules.rule[0]
    // 获取rule的值
    const newValue = safeGet(data, rule.key)
    const value = rule.value
    if (newValue !== null) {
      let flag = true
      switch (rule.option) {
        case '>':
          flag = value > newValue
          break
        case '>=':
          flag = value >= newValue
          break
        case '<':
          flag = value < newValue
          break
        case '<=':
          flag = value <= newValue
          break
        case 'includes':
          flag = newValue.toString().includes(value.toString())
          break
        case 'not_includes':
          flag = !newValue.toString().includes(value.toString())
          break
        default:
          flag = true
      }
      console.log('匹配状态：', `${newValue} ${rule.option} ${value}`, flag)
      // 匹配了
      if (!flag) {
        await action(rules.action, server, rule.key, newValue, rules.user)
        rules.count += 1
        await rules.save()
        return { action: rules.action, value: newValue }
      }
      return {}
    } else {
      return {}
    }
  } else {
    return {}
  }
}

async function handleMessage(data) {
  const { client_id, token } = data
  const server = await Server.findOne({ _id: client_id, token })
  if (!server) {
    return console.log('服务器不存在 丢弃')
  }
  const { action, value } = await rules(server, data)
  await Stream.create({
    name: action ? '触发告警' : `${server.host} 数据流`,
    struct: data,
    server: server._id,
    action,
    remark: value ? `触发值: ${value}` : 'UDP',
    user: server.user,
  })
}

function udp() {
  const dgram = require('dgram')
  const server = dgram.createSocket('udp4')

  server.on('error', (err) => {
    console.log(`服务器异常：\n${err.stack}`)
    server.close()
    process.exit(0)
  })

  server.on('message', (msg, rinfo) => {
    console.log(msg.toString())
    try {
      handleMessage(JSON.parse(msg))
    } catch (e) {
      console.log('不是标准 JSON ')
    }
  })

  server.on('listening', () => {
    const address = server.address()
    console.log(`服务器监听 ${address.address}:${address.port}`)
  })

  server.bind(7001, '0.0.0.0')
}

function tcp() {
  require('net')
}

function safeGet(data, str) {
  let _data = { ...data }
  let flag = {}
  try {
    str.split('.').forEach((key) => {
      flag = _data[key]
      _data = flag
    })
    return flag
  } catch (e) {
    return null
  }
}

// console.log(safeGet({ sex: { age: { name: 'wivwiv' } } }, 'sex.age.name'))
udp()
tcp()
